package com.sugon.modules.device.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.sugon.dao.DevAmRulesDao;
import com.sugon.dao.DevAmRulesOptionDao;
import com.sugon.dao.DevPlanRuleAmDao;
import com.sugon.entity.*;
import com.sugon.modules.base.consts.SysApproveStatusConst;
import com.sugon.modules.base.model.vo.BaseApproveParamVO;
import com.sugon.modules.base.model.vo.ProcessProgressConst;
import com.sugon.modules.device.model.vo.SaveDevAmRuleParam;
import com.sugon.modules.device.service.IDeviceAmPlanManager;
import com.sugon.modules.device.service.IDeviceAmRulesManager;
import com.sugon.modules.sys.consts.ProcessApproveStatus;
import com.sugon.modules.sys.consts.ProcessProgressStatus;
import com.sugon.service.*;
import com.sugon.utils.ProcessInfoEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author ： YuXD
 * @description：
 * @date ： 2023-01-24
 * @version: 1.0
 */
@Service
public class DeviceAmRulesManagerImpl implements IDeviceAmRulesManager {

    @Autowired
    private SysMsgService msgService;
    @Autowired
    private SysProcessInfoService processInfoService;
    @Resource
    private DevAmRulesDao devAmRulesDao;
    @Resource
    private DevPlanRuleAmDao devPlanRuleAmDao;
    @Resource
    private DevAmPlanItemService devAmPlanItemService;
    @Resource
    private DevAmRulesOptionService devAmRulesOptionService;
    @Resource
    private DevAmRulesService devAmRulesService;
    @Resource
    private DevMainBaseAmService devAmOptionService;
    @Resource
    private DevAmRulesOptionDao devAmRulesOptionDao;
    @Resource
    private IDeviceAmPlanManager devAmPlanManager;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean createDeviceAmMaintenanceRules(SaveDevAmRuleParam rulesParam) {
        // 设置基础信息
        DevAmRulesEntity amMaintenanceRules = new DevAmRulesEntity();
        CopyOptions copyOptions = CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true);
        BeanUtil.copyProperties(rulesParam, amMaintenanceRules, copyOptions);
        amMaintenanceRules.setProgress(ProcessProgressConst.NEW);
        amMaintenanceRules.setIsValid(1);
        if (StrUtil.isEmpty(amMaintenanceRules.getRuleName())) {
            amMaintenanceRules.setRuleName(rulesParam.getDevName() + "_" + "维护规程");
        }
        if (StrUtil.isEmpty(amMaintenanceRules.getPlanCon())) {
            amMaintenanceRules.setPlanCon("无");
        }
        int rows = devAmRulesService.save(amMaintenanceRules);
        if (rows > 0) {
            // 1、根据供应厂商编码、设备类别和规程类型查询可关联的设备维护项列表，并建立关系
            String devMaintenanceRuleId = amMaintenanceRules.getId();
            List<DevMainBaseAmEntity> devMainBaseList = devAmOptionService.getBySupplyAndType(rulesParam.getDevSupply(), rulesParam.getDevTypeS());
            if (CollectionUtil.isNotEmpty(devMainBaseList)) {
                for (DevMainBaseAmEntity amItem : devMainBaseList) {
                    //维护规程与维护库关联
                    DevAmRulesOptionEntity amRulesItem = new DevAmRulesOptionEntity(devMaintenanceRuleId, amItem.getId());
                    devAmRulesOptionService.save(amRulesItem);
                }
            }
            // 2、修改进度为部门审核中
            amMaintenanceRules.setProgress(ProcessProgressConst.DEPT_APPROVING);
            devAmRulesService.update(amMaintenanceRules);
        }
        return rows > 0;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean addMaintenanceRuleOption(String planId, String mainBaseId) {
        // 保存自主维护规程项信息
        DevAmRulesOptionEntity amRulesOption = new DevAmRulesOptionEntity(planId, mainBaseId);
        int saveFlag = devAmRulesOptionService.save(amRulesOption);
        cn.hutool.core.lang.Assert.isTrue(saveFlag > 0);
        // 查询设备维护规程信息
        DevAmRulesEntity devAmRules = devAmRulesService.queryObject(planId);
        Assert.notNull(devAmRules);
        // 如果要添加的维护项所在的规程已关联某个执行中的设备维护计划，那么需要添加设备维护计划项
        List<DevAmPlanEntity> amPlanList = devPlanRuleAmDao.findMatched(planId);
        if (CollectionUtil.isNotEmpty(amPlanList)) {
            DevAmPlanItemEntity amPlanItem;
            for (DevAmPlanEntity amPlan : amPlanList) {
                amPlanItem = new DevAmPlanItemEntity();
                amPlanItem.setPlanId(amPlan.getId());
                amPlanItem.setMainBaseId(mainBaseId);
                amPlanItem.setMonthNum(1);
                amPlanItem.setDayNum(1);
                amPlanItem.setDevId(devAmRules.getDevId());
                amPlanItem.setRemark("调整规程时，系统自动添加！");
                devAmPlanItemService.save(amPlanItem);
            }
        }
        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public DevAmRulesEntity deleteMaintenanceRuleOption(String id) {
        /*
            当设备维护规程项变化时，
            如果当前规程已关联设备维护计划，那么
         */
        DevAmRulesOptionEntity devAmRulesOption = devAmRulesOptionService.queryObject(id);
        cn.hutool.core.lang.Assert.notNull(devAmRulesOption);
        DevAmRulesEntity devAmRule = devAmRulesService.queryObject(devAmRulesOption.getPlanId());
        Assert.notNull(devAmRule, "维护规程[" + devAmRulesOption.getPlanId() + "]不存在，请联系管理员！");
        if (NumberUtil.equals(ProcessProgressConst.PASSED, devAmRule.getProgress())) {
            // 克隆时需要排除的维护项ID
            List<String> excludePmItemList = CollectionUtil.newArrayList(devAmRulesOption.getMainBaseId());
            devAmRule = cloneDevPmRule(devAmRulesOption.getPlanId(), excludePmItemList, null);
        } else {
            int deleteFlag = devAmRulesOptionService.delete(id);
            cn.hutool.core.lang.Assert.isTrue(deleteFlag > 0);
        }
        return devAmRule;
    }

    /**
     * 对已有的设备维护规程进行克隆，排除掉需要排除的，添加需要新增的
     *
     * @param originalPmRuleId  原设备维护规程iD
     * @param excludePmItemList 需要排除的设备维护项
     * @param addPmItemList     需要添加的设备维护项
     * @return
     */
    @Override
    public DevAmRulesEntity cloneDevPmRule(String originalPmRuleId, List<String> excludePmItemList, List<String> addPmItemList) {
        DevAmRulesEntity devAmRule = devAmRulesService.queryObject(originalPmRuleId);
        Assert.notNull(devAmRule, "维护规程[" + originalPmRuleId + "]不存在，请联系管理员！");
        // 获取原维护项列表
        List<DevAmRulesOptionEntity> originalAmOptionList = devAmRulesOptionService.getByPlanId(originalPmRuleId);
        /*
            理论上一个设备 处于新建状态的只有一个
            1、每次克隆时首先去判断当前设备是否有一个新建的设备维护规程
            如果有则沿用，没有则新建
            2、从需要克隆的设备维护规程项中排除需要排除的，添加需要新增的
            3、保存关联关系
         */
        List<DevAmRulesEntity> existedNewPmRuleList = devAmRulesService.list(devAmRule.getDevId(), ProcessProgressConst.DEPT_APPROVING, 1);
        if (CollectionUtil.isNotEmpty(existedNewPmRuleList)) {
            // 检测下处于新增状态的该设备维护规程是否沿用的是一个规程
            devAmRule = existedNewPmRuleList.get(0);
            if (StrUtil.isEmpty(devAmRule.getPreRuleId()) || !devAmRule.getPreRuleId().equals(originalPmRuleId)) {
                devAmRule.setPreRuleId(originalPmRuleId);
                devAmRulesService.update(devAmRule);
            }
            // 获取存在的设备维护项列表
            originalAmOptionList = devAmRulesOptionService.getByPlanId(devAmRule.getId());
            // 清空下既存的，防止重复
            devAmRulesOptionDao.clearAllByRuleId(devAmRule.getId());
        } else {
            devAmRule.setPreRuleId(devAmRule.getId());
            devAmRule.setProgress(ProcessProgressConst.DEPT_APPROVING);
            devAmRule.setIsValid(1);
            devAmRulesService.save(devAmRule);
        }
        // 获取最新的设备维护项列表
        List<String> newlyDevPmRuleItemList = buildPmOptionList(originalAmOptionList, excludePmItemList, addPmItemList);
        // 保存设备维护项
        if (CollectionUtil.isNotEmpty(newlyDevPmRuleItemList)) {
            DevAmRulesOptionEntity devAmRulesOption;
            for (String newlyDevPmRuleItem : newlyDevPmRuleItemList) {
                devAmRulesOption = new DevAmRulesOptionEntity(devAmRule.getId(), newlyDevPmRuleItem);
                devAmRulesOptionService.save(devAmRulesOption);
            }
        }
        return devAmRule;
    }

    /**
     * 构建最终的设备维护规程项列表
     * 逻辑：从devPmRuleId指定的规程维护项中排除掉excludePmItemList，新增addPmItemList
     * 同时去重
     *
     * @param originalAmOptionList 原始设备维护规程
     * @param excludeAmItemList    需要排除的设备维护项ID列表
     * @param addAmItemList        需要添加的设备维护项ID列表
     * @return
     */
    private List<String> buildPmOptionList(List<DevAmRulesOptionEntity> originalAmOptionList, List<String> excludeAmItemList, List<String> addAmItemList) {
        // 新建一个列表，将原有的规程项优先放置进去
        List<String> newlyDevPmRuleItemList = CollectionUtil.newArrayList();
        if (CollectionUtil.isNotEmpty(originalAmOptionList)) {
            newlyDevPmRuleItemList.addAll(originalAmOptionList.stream().map(DevAmRulesOptionEntity::getMainBaseId).collect(Collectors.toList()));
        }
        // 排除掉需要排除的
        if (CollectionUtil.isNotEmpty(excludeAmItemList)) {
            newlyDevPmRuleItemList = newlyDevPmRuleItemList.stream().filter(devPmOptionId -> !excludeAmItemList.contains(devPmOptionId)).collect(Collectors.toList());
        }
        // 添加需要添加的
        if (CollectionUtil.isNotEmpty(addAmItemList)) {
            newlyDevPmRuleItemList.addAll(addAmItemList);
            newlyDevPmRuleItemList = newlyDevPmRuleItemList.stream().distinct().collect(Collectors.toList());
        }
        return newlyDevPmRuleItemList;
    }

    @Override
    public boolean workshopBatchApprove(BaseApproveParamVO approveParam) {
        List<String> approveIdList = approveParam.getApproveIdList();
        int totalRows = 0;
        DevAmRulesEntity devAmRules;
        // 获取审核结果
        int approveStatus = approveParam.getStatus();

        for (String approveItemId : approveIdList) {
            devAmRules = devAmRulesService.queryObject(approveItemId);
            Assert.notNull(devAmRules, "维护规程信息不存在，请确认！");
            // 校验规程进度
            Assert.isTrue(NumberUtil.equals(ProcessProgressConst.DEPT_APPROVING, devAmRules.getProgress()));
            // 创建公共消息
            SysMsgEntity sysMsg = new SysMsgEntity();
            sysMsg.setDataId(approveItemId);
            sysMsg.setDataUrl("../device/devmaintenplan.html?Id=" + approveItemId);
            // 如果审核通过
            if (approveStatus == SysApproveStatusConst.PASSED) {
                devAmRules.setProgress(ProcessProgressConst.PASSED);
                int rows = devAmRulesService.update(devAmRules);
                if (rows > 0) {
                    totalRows += rows;
                    // 替换设备维护规程
                    if (StrUtil.isNotEmpty(devAmRules.getPreRuleId())) {
                        // 替换设备维护规程
                        devAmPlanManager.changeAmRule(devAmRules.getPreRuleId(), devAmRules.getId());
                    }
                    // 1、失效当前设备的早期版本
                    devAmRulesDao.invalid(devAmRules.getDevId(), approveItemId);
                    // 2、生成流程节点信息
                    processInfoService.saveProcessInfo(null, approveItemId, ProcessInfoEnum.DEV_WHGC, ProcessApproveStatus.PASSED_WITH_APPROVE, null, approveParam.getRemark(), ProcessProgressStatus.END);
                    // 3、删除所有消息
                    sysMsg.setRemark(StrUtil.format(ProcessInfoEnum.DEV_WHGC.getPassedMsgTemplate()));
                    sysMsg.setDataFlag(ProcessProgressStatus.END + "");
                    msgService.addApproveItem(ProcessInfoEnum.DEV_WHGC, sysMsg, 1);
                }
            } else if (approveStatus == SysApproveStatusConst.NOT_PASSED) {
                devAmRules.setProgress(ProcessProgressConst.NOT_PASSED);
                int rows = devAmRulesService.update(devAmRules);
                if (rows > 0) {
                    totalRows += rows;
                    // 1、生成流程节点信息
                    processInfoService.saveProcessInfo(null, approveItemId, ProcessInfoEnum.DEV_WHGC, approveStatus, null, approveParam.getRemark(), ProcessProgressStatus.ING);
                    // 2、通知编制人维护规程未通过审核
                    sysMsg.setUserId(devAmRules.getOrgUserId());
                    sysMsg.setRemark(StrUtil.format(ProcessInfoEnum.DEV_WHGC.getNotPassedMsgTemplate(), devAmRules.getRuleName(), approveParam.getRemark()));
                    msgService.addApproveItem(ProcessInfoEnum.DEV_WHGC, sysMsg, 0);
                }
            }
        }
        return totalRows == approveIdList.size();
    }

}

